home *** CD-ROM | disk | FTP | other *** search
- /* Internet LPD Server subroutines
- * written by David Johnson (dave@cs.olemiss.edu)
- *
- * This code is in the public domain.
- *
- * Revision History:
- *
- * Revision 1.4 91/09/27 dave (from Hans-Juergen)
- * Changed definitions of default files to handle changing NOS logical
- * root directory
- * Actually retrieve the page cost (co) from printcap for pac
- *
- * Revision 1.3 91/09/19 dave
- * Read the ty capability even when interface is not an internal device
- *
- * Revision 1.2 91/09/17 dave
- * Moved output processing flags to device structure so all device types
- * can use them
- *
- * Revision 1.1 91/09/14 dave (from marko winblad)
- * Perform an ioctl on DOS device to make sure it is opened in "binary" mode
- *
- * Revision 1.0 91/09/04 dave
- * Initial Release
- *
- */
- #include <stdio.h>
- #include <fcntl.h>
- #include <ctype.h>
- #include <time.h>
- #include <sys/stat.h>
- #ifdef __TURBOC__
- #include <io.h>
- #include <dir.h>
- #endif
- #include "global.h"
- #include "mbuf.h"
- #include "proc.h"
- #include "iface.h"
- #include "asy.h"
- #include "i8250.h"
- #include "devparam.h"
- #include "socket.h"
- #include "dirutil.h"
- #include "commands.h"
- #include "files.h"
- #include "lp.h"
- #include "lpd.h"
- #include "lpdfilt.h"
-
- /* in files.c */
- extern char *roordircat __ARGS((char *directory));
-
- /* in lpd.c */
- extern int is_lpd_active __ARGS((void));
-
- /* local functions - public */
- int get_acct_info __ARGS((char *queue, char **af, int *pc));
- int get_job_list __ARGS((char *directory, struct job_entry **job_list));
- char **get_queue_list __ARGS((void));
- char *get_spool_dir __ARGS((char *queue));
- struct LPDstatus *get_status_entry __ARGS((char *queue));
- int is_unspooler_active __ARGS((char *queue, char **job));
- int kill_unspooler __ARGS((char *queue));
- void lpd_log __ARGS((struct LPDtrans *LPD, char *message, ...));
- char *read_printcap __ARGS((struct LPDtrans *LPD, char *queue));
- int read_status __ARGS((char *queue, unsigned int *flags, unsigned int *next_seq, char **message));
- void set_status_message __ARGS((char **dest, char *message, ...));
- char *time_string __ARGS((void));
-
- /* local functions - exported to lpd.c */
- void free_queue_status __ARGS((void));
- int get_new_sequence_no __ARGS((struct LPDtrans *LPD));
- int init_queue_status __ARGS((void));
-
- /* local functions - exported to lpdunsp.c */
- int cf_parse __ARGS((struct LPDtrans *LPD, FILE *cfp));
- int close_device __ARGS((struct LPDtrans *LPD));
- void free_job __ARGS((struct LPDjob *job));
- struct LPDdevice *get_device_entry __ARGS((char *device_name));
- int open_device __ARGS((struct LPDtrans *LPD));
- int save_status __ARGS((char *queue, unsigned int flags, unsigned int next_seq));
-
- /* local functions - exported to lpc.c */
- int clear_status_flag __ARGS((char *queue, int flag));
- int get_job_count __ARGS((char *queue));
- int set_status_flag __ARGS((char *queue, int flag));
- int signal_queue __ARGS((char *queue));
-
- /* local functions - private */
- static int job_compare __ARGS((char *entry1, char *entry2));
- static char *pc_get_entry __ARGS((char *bp, char *name));
- static int pc_get_number __ARGS((char *bp, char *id));
- static int pc_get_flag __ARGS((char *bp, char *id));
- static char *pc_get_string __ARGS((char *bp, char *id, char **area));
- static unsigned int get_queue_count __ARGS((void));
- static char *get_primary_queue_name __ARGS((char *queue));
- static void read_lock_file __ARGS((char *directory, unsigned int *flags, unsigned int *next_seq));
- static void set_device_params __ARGS((struct LPDtrans *LPD, char *params));
- static void write_lock_file __ARGS((char *directory, unsigned int flags, unsigned int next_seq));
- static int load_status __ARGS((char *queue, unsigned int *flags, unsigned int *next_seq));
- static void write_lock_file __ARGS((char *directory, unsigned int flags, unsigned int next_seq));
- static void read_lock_file __ARGS((char *directory, unsigned int *flags, unsigned int *next_seq));
- static void i_lpd_log __ARGS((struct LPDtrans *LPD, char *message, va_list args));
- static void i_set_status_message __ARGS((char **dest, char *message, va_list args));
-
- /* Status messages */
- static char checking[] = "Checking queue at %s";
- static char done[] = "Work done at %s";
- static char processing[] = "Processing, active job started %s";
- static char busy_device[] = "Waiting for %s to become free since %s";
- static char offline_device[] = "Waiting for %s to become ready since %s (offline?)";
- static char device_opened[] = "Printer %s output %s opened at %s";
-
-
- static struct LPDstatus *queue_list;
-
- /*
- * All devices which are supported
- */
- static struct LPDdevice device_list[] = {
- {"LPT1", 0},
- {"LPT2", 0},
- {"LPT3", 0},
- {"COM1", 0},
- {"COM2", 0},
- {"COM3", 0},
- {"COM4", 0},
- {"sl1" , 0}, /* internal NOS serial interfaces */
- {"sl2" , 0},
- {"sl3" , 0},
- {"sl4" , 0},
- { NULL , 0}};
-
-
- /*
- * Scan spool directory and return the list of jobs found in job order
- */
- int
- get_job_list( directory, job_list )
- char *directory;
- struct job_entry **job_list;
- {
- char *strdup(), *path, *cf_path;
- struct ffblk file_info;
- struct stat statbuf;
- struct job_entry *tmp_job_list;
- unsigned int job_count, job_list_size;
-
- path = pathname( directory, "cf*.*" );
- job_count = 0;
- tmp_job_list = callocw( 20, sizeof( struct job_entry ) );
- job_list_size = 20;
- if( findfirst( path, &file_info, 0 ) == 0 ) {
- tmp_job_list[job_count].j_name = strdup( file_info.ff_name );
- tmp_job_list[job_count].j_priority = file_info.ff_name[2];
- cf_path = pathname( directory, file_info.ff_name );
- stat( cf_path, &statbuf );
- free( cf_path );
- tmp_job_list[job_count].j_time = statbuf.st_mtime;
- job_count++;
- YIELD;
- while( findnext( &file_info ) == 0 ) {
- tmp_job_list[job_count].j_name = strdup( file_info.ff_name );
- tmp_job_list[job_count].j_priority = file_info.ff_name[2];
- cf_path = pathname( directory, file_info.ff_name );
- stat( cf_path, &statbuf );
- free( cf_path );
- tmp_job_list[job_count].j_time = statbuf.st_mtime;
- if( ++job_count > job_list_size ) {
- job_list_size += 20;
- tmp_job_list = realloc( tmp_job_list,
- job_list_size*sizeof(struct job_entry) );
- }
- YIELD;
- }
- YIELD;
- qsort( (char *)tmp_job_list, job_count, sizeof( struct job_entry ), job_compare );
- }
- free( path );
-
- if( job_count == 0 ) {
- free( tmp_job_list );
- *job_list = NULL;
- } else {
- *job_list = tmp_job_list;
- }
- YIELD;
- return job_count;
- }
-
- /*
- * Compare two job entries for qsort
- */
- static int
- job_compare( entry1, entry2 )
- char *entry1, *entry2;
- {
- struct job_entry *p1, *p2;
-
- p1 = (struct job_entry *)entry1;
- p2 = (struct job_entry *)entry2;
- if( (p1)->j_priority < (p2)->j_priority )
- return -1;
- if( (p1)->j_priority > (p2)->j_priority )
- return 1;
- if( (p1)->j_time < (p2)->j_time )
- return -1;
- if( (p1)->j_time > (p2)->j_time )
- return 1;
- return 0;
- }
-
- /*
- * Convert string to upper case
- */
- static void
- uppercase_string( string )
- char *string;
- {
- char *cp = string;
-
- while( *cp ) {
- if( islower( *cp ) )
- *cp = toupper( *cp );
- cp++;
- }
- }
-
- /*
- * Read the printcap entries use in printing and spooling.
- * Return the primary queue name.
- */
- char *
- read_printcap( LPD, queue )
- struct LPDtrans *LPD;
- char *queue;
- {
- struct iface *ifp;
- char *bp, *pcptr, *path;
- char *primary_name;
- FILE *fp;
-
- LPD->pc = (struct LPDpr *)mallocw( sizeof(struct LPDpr) );
- bp = LPD->pc->buffer;
-
- if( (primary_name = pc_get_entry( bp, queue )) == NULL ) {
- tprintf( "queue %s not found.\n", queue );
- return NULL;
- }
- LPD->name = primary_name;
-
- pcptr = LPD->pc->strings;
-
- if( (LPD->pc->SD = pc_get_string( bp, "sd", &pcptr )) == NULL )
- LPD->pc->SD = Lpdsd;
- if( *LPD->pc->SD != '/' )
- LPD->pc->SD = rootdircat( LPD->pc->SD );
-
- /*
- * Check that spool directory exists
- */
- path = pathname( LPD->pc->SD, "testfile" );
- fp = fopen( path, "w" );
- if( fp == NULL ) {
- tprintf( "lpd: spool directory (%s) may not exist\n", LPD->pc->SD );
- free( path );
- return NULL;
- }
- fclose( fp );
- remove( path );
- free( path );
- YIELD;
-
- if( (LPD->pc->LP = pc_get_string( bp, "lp", &pcptr )) == NULL )
- LPD->pc->LP = D_DEVLP;
-
- if( (ifp = if_lookup( LPD->pc->LP )) != NULL ) {
- /* INTERNAL DEVICE; MUST BE SERIAL PORT */
-
- if( (LPD->pc->BR = pc_get_number( bp, "br" )) < 0 )
- LPD->pc->BR = D_BAUDRATE;
- (*ifp->ioctl)( ifp, PARAM_SPEED, TRUE, LPD->pc->BR );
- } else {
- uppercase_string( LPD->pc->LP );
- }
- LPD->pc->TY = pc_get_string( bp, "ty", &pcptr );
-
- if( (LPD->pc->LF = pc_get_string( bp, "lf", &pcptr )) == NULL )
- LPD->pc->LF = Lpdlogfile;
- if( *LPD->pc->LF != '/' )
- LPD->pc->LF = rootdircat( LPD->pc->LF );
- if( (LPD->pc->FF = pc_get_string( bp, "ff", &pcptr )) == NULL )
- LPD->pc->FF = D_FF;
- if( (LPD->pc->PW = pc_get_number( bp, "pw" )) < 0 )
- LPD->pc->PW = D_WIDTH;
- if( (LPD->pc->PL = pc_get_number( bp, "pl" )) < 0 )
- LPD->pc->PL = D_LENGTH;
- if( (LPD->pc->PX = pc_get_number( bp, "px" )) < 0 )
- LPD->pc->PX = D_PWIDTH;
- if( (LPD->pc->PY = pc_get_number( bp, "py" )) < 0 )
- LPD->pc->PY = D_PLENGTH;
-
- if( (LPD->pc->MC = pc_get_number( bp, "mc" )) < 0 )
- LPD->pc->MC = D_MAXCOPIES;
- if( (LPD->pc->MX = pc_get_number( bp, "mx" )) < 0 )
- LPD->pc->MX = D_MAXJOBSIZE;
-
- if( (LPD->pc->IF = pc_get_string( bp, "if", &pcptr )) == NULL )
- LPD->pc->IF = D_IF;
-
- if( (LPD->pc->OF = pc_get_string( bp, "of", &pcptr )) == NULL )
- LPD->pc->OF = D_OF;
-
- if( (LPD->pc->FX = pc_get_string( bp, "fx", &pcptr )) == NULL )
- LPD->pc->FX = D_FILTERS;
-
- YIELD;
-
- /* Other filter specifications - presently not used */
- LPD->pc->CF = pc_get_string( bp, "cf", &pcptr );
- LPD->pc->DF = pc_get_string( bp, "df", &pcptr );
- LPD->pc->GF = pc_get_string( bp, "gf", &pcptr );
- LPD->pc->NF = pc_get_string( bp, "nf", &pcptr );
- LPD->pc->TF = pc_get_string( bp, "tf", &pcptr );
- LPD->pc->VF = pc_get_string( bp, "vf", &pcptr );
-
- LPD->pc->CM = pc_get_string( bp, "cm", &pcptr );
- LPD->pc->AF = pc_get_string( bp, "af", &pcptr );
- if( *LPD->pc->AF != '/' )
- LPD->pc->AF = rootdircat( LPD->pc->AF );
- LPD->pc->LD = pc_get_string( bp, "ld", &pcptr );
- LPD->pc->TR = pc_get_string( bp, "tr", &pcptr );
- LPD->pc->JL = pc_get_string( bp, "jl", &pcptr );
- LPD->pc->JT = pc_get_string( bp, "jt", &pcptr );
- LPD->pc->FL = pc_get_string( bp, "fl", &pcptr );
- LPD->pc->FT = pc_get_string( bp, "ft", &pcptr );
-
- YIELD;
-
- LPD->pc->AB = pc_get_flag( bp, "ab" );
- LPD->pc->FO = pc_get_flag( bp, "fo" );
- LPD->pc->FQ = pc_get_flag( bp, "fq" );
- LPD->pc->HL = pc_get_flag( bp, "hl" );
- LPD->pc->SB = pc_get_flag( bp, "sb" );
- LPD->pc->SC = pc_get_flag( bp, "sc" );
- LPD->pc->SF = pc_get_flag( bp, "sf" );
- LPD->pc->SH = pc_get_flag( bp, "sh" );
- LPD->pc->SS = pc_get_flag( bp, "ss" );
-
- /* PostScript capabilities */
- LPD->pc->PS = pc_get_string( bp, "ps", &pcptr );
- LPD->pc->PE = pc_get_string( bp, "pe", &pcptr );
- LPD->pc->DP = pc_get_flag( bp, "dp" );
-
- YIELD;
- return( primary_name );
- }
-
- /*
- * Set the device characteristics of an internal NOS interface
- */
- static void
- set_device_params( LPD, params)
- struct LPDtrans *LPD;
- char *params;
- {
- struct iface *ifp = NULL;
- int negate;
- char *tempparams, *option;
-
- if( LPD->status->type == INTERNAL )
- ifp = LPD->status->device.ifp;
-
- tempparams = strdup( params );
-
- option = strtok( tempparams, " " );
- while( option ) {
- negate = 0;
- if( *option == '-' ) {
- negate = 1;
- option++;
- }
- if( strncmp( option, "even", 4 ) == 0 && ifp ) {
-
- if( negate ) /* not even */
- (*ifp->ioctl)( ifp, PARAM_PARITY, TRUE, 0 );
- else /* even */
- (*ifp->ioctl)( ifp, PARAM_PARITY, TRUE, 1 );
-
- } else if( strncmp( option, "odd", 3 ) == 0 && ifp ) {
-
- if( negate ) /* not odd */
- (*ifp->ioctl)( ifp, PARAM_PARITY, TRUE, 0 );
- else /* odd */
- (*ifp->ioctl)( ifp, PARAM_PARITY, TRUE, 2 );
-
- } else if( strncmp( option, "rts", 3 ) == 0 && ifp ) {
-
- (*ifp->ioctl)( ifp, PARAM_RTS, TRUE, !negate );
-
- } else if( strncmp( option, "dtr", 3 ) == 0 && ifp ) {
-
- (*ifp->ioctl)( ifp, PARAM_DTR, TRUE, !negate );
-
- } else if( strncmp( option, "nl", 2 ) == 0 ) {
-
- if( negate )
- LPD->device->flags &= ~CRMOD;
- else
- LPD->device->flags |= CRMOD;
-
- } else if( strncmp( option, "tabs", 4 ) == 0 ) {
-
- if( negate )
- LPD->device->flags |= XTABS;
- else
- LPD->device->flags &= ~XTABS;
-
- }
- option = strtok( NULL, " " );
- }
- free( tempparams );
- }
-
- /*
- * Open the specified device if it is not busy, else wait for it to free.
- */
- int
- open_device( LPD )
- struct LPDtrans *LPD;
- {
- struct LPDstatus *status = LPD->status;
-
- if( status->device_open == 0 ) {
- set_status_message( &LPD->status->message, busy_device, LPD->pc->LP, time_string() );
- while( LPD->device->busy ) /* another unspooler is using */
- YIELD;
-
- if( (status->device.ifp = if_lookup( LPD->pc->LP )) == NULLIF ) {
- /* MUST BE A DOS FILE DEVICE */
-
- status->type = EXTERNAL;
- if( (status->device.fp = fopen( LPD->pc->LP, "ab" )) == NULL ) {
- tprintf( "device could not be opened\n" );
- return -1;
- }
- /*
- * Make sure device is opened in "binary" mode
- */
- #ifdef LPD_DEBUG
- tprintf( "isatty(%d) returns %d\n",
- fileno( status->device.fp ),
- isatty( fileno( status->device.fp ) ));
- tflush();
- #endif
- if( isatty( status->device.fp->fd ) ) {
- #ifdef LPD_DEBUG tprintf( "ioctl(%d,0) returns %04x\n",
- fileno( status->device.fp ),
- ioctl( fileno( status->device.fp ), 0);
- tflush();
- #endif
- ioctl( fileno( status->device.fp ), 1,
- 0xff &
- (ioctl( fileno( status->device.fp ),0)
- | 0x20 ) );
- }
- #ifdef LPD_DEBUG
- tprintf( "ioctl(%d,0) returns %04x\n",
- fileno( status->device.fp ),
- ioctl( fileno( status->device.fp ), 0 ) );
- tflush();
- #endif
- } else {
- if( (status->device.ifp)->dev >= ASY_MAX
- || Asy[(status->device.ifp)->dev].iface != status->device.ifp ){
- /* INVALID INTERNAL INTERFACE; MAKE EXTERNAL */
-
- status->type = EXTERNAL;
- if( (status->device.fp = fopen( LPD->pc->LP, "ab" )) == NULL ) {
- tprintf( "device could not be opened\n" );
- return -1;
- }
- } else {
- status->type = INTERNAL;
- }
- }
- if( LPD->pc->TY )
- set_device_params( LPD, LPD->pc->TY );
- LPD->device->busy = 1; /* mark device as busy */
- LPD->status->device_open = 1;
- LPD->status->jobno = 0;
- set_status_message( &LPD->status->message, device_opened, LPD->name, LPD->pc->LP, time_string() );
- }
- return 0;
- }
-
- /*
- * Close the device file handle and free device
- */
- int
- close_device( LPD )
- struct LPDtrans *LPD;
- {
- if( LPD->status->device_open ) {
- if( LPD->status->type == EXTERNAL ) {
- fclose( LPD->status->device.fp );
- LPD->status->device.fp = (FILE *)0;
- }
- LPD->status->device_open = 0;
- LPD->device->busy = 0;
- }
- }
-
- /*
- * Read the control file and extract necessary entries.
- * Returns -1 if data file(s) is not found or size exceeds MX.
- */
- int
- cf_parse( LPD, cfp )
- struct LPDtrans *LPD;
- FILE *cfp;
- {
- char line[81], *ptr, *strdup();
- char *path;
- struct LPDjob *job;
-
- job = LPD->job;
- while( fgets( line, 80, cfp ) != NULL ) {
- rip( line );
- switch( *line ) {
- case 'N':
- case 'U':
- /* ignore */
- break;
- case 'C':
- job->class = strdup( line+1 );
- break;
- case 'D':
- job->date = strdup( line+1 );
- break;
- case 'H':
- job->hostname = strdup( line+1 );
- break;
- case 'I':
- job->indent = atoi( line+1 );
- break;
- case 'J':
- job->jobname = strdup( line+1 );
- break;
- case 'L':
- job->username = strdup( line+1 );
- break;
- case 'M':
- job->mail = strdup( line+1 );
- break;
- case 'P':
- job->person = strdup( line+1 );
- break;
- case 'S':
- job->noheader = strdup( line+1 );
- break;
- case 'R':
- job->account = strdup( line+1 );
- break;
- case 'W':
- job->width = atoi( line+1 );
- break;
- case 'T':
- job->title = strdup( line+1 );
- break;
- default:
- if( islower( *line ) ) {
- struct stat fstatus;
-
- if( strchr( LPD->pc->FX, *line ) == NULL )
- return -1;
- path = pathname( LPD->pc->SD, line+1 );
- if( stat( path, &fstatus ) != 0 ) {
- free( path );
- lpd_log( LPD, "cf_parse: %s not found", line+1 );
- return -1;
- }
- free( path );
- job->size += (fstatus.st_size + 1023)/1024;
- if( LPD->pc->MX && job->size > LPD->pc->MX ) {
- lpd_log( LPD, "cf_parse: job %s exceeds max. job size", job->jobname );
- return -1;
- }
- }
- }
- YIELD;
- }
-
- /*
- * Handle missing items
- */
- if( LPD->job->width == 0 )
- LPD->job->width = LPD->pc->PW;
- if( LPD->job->class == NULL && LPD->job->hostname )
- LPD->job->class = strdup( LPD->job->hostname );
-
- return 0;
- }
-
- /*
- * free the job fields allocated in cf_parse
- */
- void
- free_job( job )
- struct LPDjob *job;
- {
- if( job == NULL )
- return;
-
- if( job->class )
- free( job->class );
- if( job->date )
- free( job->date );
- if( job->hostname )
- free( job->hostname );
- if( job->jobname )
- free( job->jobname );
- if( job->username )
- free( job->username );
- if( job->mail )
- free( job->mail );
- if( job->person )
- free( job->person );
- if( job->noheader )
- free( job->noheader );
- if( job->account )
- free( job->account );
- if( job->title )
- free( job->title );
- free( job );
- job = NULL;
- }
-
- /******************************************************************************
- ** **
- ** Printcap file handling routines **
- ** **
- ******************************************************************************/
-
- /*
- ** pc_get_entry - get the printcap entry for printer name, and put it
- ** in bp (which must be an array of 1024 chars). Returns
- ** PRIMARY_NAME if printcap entry found, NULL if not found or
- ** printcap file not found.
- */
- static char *
- pc_get_entry( bp, name )
- char *bp, *name;
- {
- FILE *fp;
- char *cp, *pn, *primary_name;
- short len = strlen( name );
-
- #ifdef LPD_DEBUG
- tprintf( "pc_get_entry( %s )\n", name );
- tflush();
- #endif
-
- if( (fp = fopen( Lpdprintcap, "r" )) == (FILE *) NULL )
- return( NULL );
-
- while( fgets( bp, 1024, fp ) != NULL ) {
- /* skip comments */
- if( *bp == '#' )
- continue;
- for( cp = bp; isspace( *cp ); cp++ )
- ;
- do {
- if( strncmp( name, cp, len ) == 0 ) {
- while( *(cp = &bp[strlen(bp) - 2]) == '\\' )
- fgets( cp, 1024, fp );
- fclose( fp );
- len = 0;
- cp = bp;
- while( *cp && *cp != ':' && *cp != '|' ) {
- ++len;
- ++cp;
- }
- primary_name = (char *)mallocw(len+1);
- cp = bp;
- pn = primary_name;
- while( *cp && *cp != ':' && *cp != '|' )
- *pn++ = *cp++;
- *pn = NULL;
- return( primary_name );
- }
- while( *cp && *cp != '|' )
- cp++;
- if( *cp ) /* skip | */
- cp++;
- } while( *cp && *cp != '\\' );
- }
- fclose( fp );
- return( NULL );
- }
-
- /*
- ** pc_get_number - get the numeric printer capability corresponding
- ** to id. Returns the value, -1 if invalid.
- */
- static int
- pc_get_number( bp, id )
- char *bp, *id;
- {
- char *cp;
- int ret;
-
- if( (cp = bp) == NULL || id == NULL )
- return( -1 );
- while( *++cp != ':' )
- ;
- for( ++cp; *cp; ) {
- while( isspace( *cp ) )
- cp++;
- if( strncmp( cp, id, 2) == 0 ) {
- while( *cp && *cp != ':' && *cp != '#' )
- cp++;
- if( *cp != '#' )
- return( -1 );
- for( ret = 0, cp++; *cp && isdigit( *cp ); cp++ )
- ret = ret * 10 + *cp - '0';
- return( ret );
- }
- while( *cp && *cp != ':' )
- cp++;
- if( *cp )
- cp++;
- }
- return( -1 );
- }
-
- /*
- ** pc_get_flag - get the boolean flag corresponding to id. Returns
- ** -1 if invalid, FALSE if the flag is not in the printcap
- ** entry, or TRUE if it is present.
- */
- static int
- pc_get_flag( bp, id )
- char *bp, *id;
- {
- char *cp;
-
- if( (cp = bp) == NULL || id == NULL )
- return( -1 );
- while( *++cp != ':' )
- ;
- for( ++cp; *cp; ) {
- while( isspace( *cp ) )
- cp++;
- if( strncmp( cp, id, 2) == 0 )
- return( TRUE );
- while( *cp && *cp != ':' )
- cp++;
- if( *cp )
- cp++;
- }
- return( FALSE );
- }
-
- /*
- ** pc_get_string - get the string capability corresponding to id and place
- ** it in area (advancing area to same time). Expand escape
- ** sequences etc. Returns the string, of NULL if it can't
- ** do it.
- */
- static char *
- pc_get_string( bp, id, area )
- char *bp, *id, **area;
- {
- char *cp, *ret;
- int i;
-
- if( (cp = bp) == NULL || id == NULL )
- return( NULL );
- while( *++cp != ':' )
- ;
- for( ++cp; *cp; ) {
- while( isspace( *cp ) )
- cp++;
- if( strncmp( cp, id, 2) == 0 ) {
- while( *cp && *cp != ':' && *cp != '=' )
- cp++;
- if( *cp != '=' )
- return( NULL );
- for( ret = *area, cp++; *cp && *cp != ':'; (*area)++, cp++ )
- switch( *cp ) {
- case '^':
- **area = *++cp - 'A';
- break;
- case '\\':
- switch( *++cp ) {
- case 'E':
- **area = '\033';
- break;
- case 'n':
- **area = '\n';
- break;
- case 'r':
- **area = '\r';
- break;
- case 't':
- **area = '\t';
- break;
- case 'b':
- **area = '\b';
- break;
- case 'f':
- **area = '\f';
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- for( i = 0; *cp && isdigit( *cp ); cp++ )
- i = i * 8 + *cp - '0';
- **area = i & 0x7f; /* strip high bit */
- cp--;
- break;
- case '^':
- case '\\':
- **area = *cp;
- break;
- }
- break;
- default:
- **area = *cp;
- }
- *(*area)++ = '\0';
- return( ret );
- }
- while( *cp && *cp != ':' )
- cp++;
- if( *cp )
- cp++;
- }
- return( NULL );
- }
-
- /*
- * Get a count of the number of queues specified in the printcap
- */
- static unsigned int
- get_queue_count()
- {
- FILE *fp;
- unsigned int queue_count = 0;
- char *buffer;
-
- #ifdef LPD_DEBUG
- tprintf( "get_queue_count()\n" );
- tflush();
- #endif
-
- if( (fp = fopen( Lpdprintcap, "r" )) == (FILE *) NULL )
- return NULL;
-
- buffer = (char *)mallocw( 1024 );
-
- while( fgets( buffer, 1024, fp ) != NULL ) {
- /* skip comments */
- if( *buffer == '#' )
- continue;
-
- if( *buffer != '\n' ) {
- queue_count++;
- while( *(buffer + strlen( buffer ) - 2) == '\\' )
- fgets( buffer, 1024, fp );
- }
- YIELD;
- }
- fclose( fp );
- free( buffer );
- return( queue_count );
- }
-
- /*
- * Scans the printcap file and extracts the names of all queues.
- */
- char **
- get_queue_list(void)
- {
- FILE *fp;
- char *cp, *strdup(), save;
- char *buffer;
- char **queue_list;
- unsigned int queue_count = 0, queue_entry = 0;
-
- #ifdef LPD_DEBUG
- tprintf( "get_queue_list()\n" );
- tflush();
- #endif
-
- queue_count = get_queue_count();
- if( queue_count == 0 ) {
- tprintf( "no queues defined in printcap file\n" );
- return NULL;
- }
- queue_list = callocw( queue_count+1, sizeof( char * ) );
-
- buffer = mallocw( 1024 );
-
- fp = fopen( Lpdprintcap, "r" );
-
- while( fgets( buffer, 1024, fp ) != NULL ) {
- /* skip comments */
- if( *buffer == '#' )
- continue;
- for( cp = buffer; isspace( *cp ) && *cp != '\n'; cp++ )
- ;
- while( *cp && *cp != '|' && *cp != ':'
- && *cp != '\\' && *cp != '\n' )
- cp++;
- save = *cp;
- *cp = NULL;
-
- if( *buffer )
- queue_list[ queue_entry++ ] = strdup( buffer );
- *cp = save;
- while( *(buffer + strlen( buffer ) - 2) == '\\' )
- fgets( buffer, 1024, fp );
- YIELD;
- }
- queue_list[ queue_entry ] = NULL;
-
- fclose( fp );
- free( buffer );
- return( queue_list );
- }
-
- /*
- * Get the SD (spool directory) associated with the specified queue
- * from the printcap
- */
- char *
- get_spool_dir( queue )
- char *queue;
- {
- char *cp, *strdup();
- char *bp, *sp, *osp; /* buffer and string pointers */
- char *primary_name;
- char *sd;
-
- bp = (char *)mallocw( 1024 );
-
- /* look up corresponding printcap entry */
-
- if( (primary_name = pc_get_entry( bp, queue )) == NULL ) {
- free( bp );
- return NULL;
- }
- free( primary_name );
- osp = sp = (char *)mallocw( 128 );
-
- if( (cp = pc_get_string( bp, "sd", &sp )) == NULL )
- cp = Lpdsd;
- if( *cp != '/' )
- cp = rootdircat( cp );
- sd = strdup( cp );
-
- free( osp );
- free( bp );
-
- return sd;
- }
-
- /*
- * Get the AF (accounting file) and CO (page cost) associated
- * with the specified queue from the printcap
- */
- int
- get_acct_info( queue, af, pc )
- char *queue, **af;
- int *pc;
- {
- char *cp, *strdup();
- char *bp, *sp, *osp; /* buffer and string pointers */
- char *primary_name;
-
- bp = (char *)mallocw( 1024 );
-
- /* look up corresponding printcap entry */
-
- if( (primary_name = pc_get_entry( bp, queue )) == NULL ) {
- free( bp );
- return 1;
- }
- free( primary_name );
- osp = sp = (char *)mallocw( 128 );
-
- if( (cp = pc_get_string( bp, "af", &sp )) == NULL ) {
- *af = NULL;
- } else {
- *af = strdup( cp );
- }
- if( **af != '/' )
- *af = rootdircat( *af );
-
- if( (*pc = pc_get_number( bp, "co" )) < 0 )
- *pc = 0;
-
- free( osp );
- free( bp );
-
- return 0;
- }
-
- /*
- * Set up internal queue status structures. Read previous status from
- * disk or create a new status file.
- */
- int
- init_queue_status(void)
- {
- char **pr, **opr, *strdup(); /* list of print queues */
- char *sd;
- unsigned int count;
- struct LPDstatus *ptr;
-
- #ifdef LPD_DEBUG
- tprintf( "init_queue_status()\n" );
- tflush();
- #endif
-
- count = get_queue_count();
- if( count == 0 ) {
- tprintf( "no queues defined in printcap file\n" );
- return -1;
- }
- queue_list = ptr = calloc( count+1, sizeof( struct LPDstatus ) );
-
- for( opr = pr = get_queue_list(); *pr; ++pr, ++ptr ){
- /* look up corresponding printcap entry */
-
- sd = get_spool_dir( *pr );
-
- read_lock_file( sd, &ptr->flags, &ptr->next_seq );
- free( sd );
-
- ptr->name = strdup( *pr );
- ptr->device_open = 0;
- ptr->type = EXTERNAL; /* These will be set on the */
- ptr->device.fp = (FILE *)0; /* call to open_device() */
- ptr->jobno = 0;
- ptr->busy = 0;
- ptr->message = NULL;
-
- free( *pr );
- }
- free( *pr ); /* null entry */
- free( opr );
-
- /* last one is NULL */
- ptr->name = NULL;
-
- return 0;
- }
-
- /*
- * Free internal queue status structures.
- */
- void
- free_queue_status(void)
- {
- struct LPDstatus *ptr;
-
- #ifdef LPD_DEBUG
- tprintf( "free_queue_status()\n" );
- tflush();
- #endif
-
- for( ptr = queue_list; ptr->name; ptr++ ) {
- free( ptr->name );
- if( ptr->message != NULL )
- free( ptr->message );
- }
- free( queue_list );
- }
-
- /*
- * Obtain new sequence number for a new job
- */
- int
- get_new_sequence_no( LPD )
- struct LPDtrans *LPD;
- {
- if( LPD->status == NULL ) {
- if( (LPD->status = get_status_entry( LPD->name )) == NULL )
- return -1;
- }
-
- LPD->status->next_seq++;
-
- write_lock_file( LPD->pc->SD, LPD->status->flags, LPD->status->next_seq );
-
- return( LPD->status->next_seq-1 );
- }
-
- /*
- * Read physical queue lock file contents. If given file does not exist,
- * one is created with the default values.
- */
- static void
- read_lock_file( directory, flags, next_seq )
- char *directory;
- unsigned int *flags;
- unsigned int *next_seq;
- {
- char *path;
- int fd;
-
- path = pathname( directory, D_LOCK );
- if( (fd = open( path, O_RDONLY )) < 0 ) {
- fd = creat( path, 0644 );
- *flags = QUEUE_ENABLED | PRINT_ENABLED;
- *next_seq = 1;
- write( fd, flags, sizeof( *flags ) );
- write( fd, next_seq, sizeof( *next_seq ) );
- lseek( fd, 0L, 0 );
- }
- read( fd, flags, sizeof( *flags ) );
- read( fd, next_seq, sizeof( *next_seq ) );
- close( fd );
- free( path );
- YIELD;
- }
-
- /*
- * Write values to physical queue lock file.
- */
- static void
- write_lock_file( directory, flags, next_seq )
- char *directory;
- unsigned int flags;
- unsigned int next_seq;
- {
- char *path;
- int fd;
-
- path = pathname( directory, D_LOCK );
- fd = open( path, O_WRONLY|O_TRUNC|O_CREAT, 0644 );
- write( fd, &flags, sizeof( flags ) );
- write( fd, &next_seq, sizeof( next_seq ) );
- close( fd );
- free( path );
- YIELD;
- }
-
- /*
- * Load the status file for the given queue and extract its contents
- */
- static int
- load_status( queue, flags, next_seq )
- char *queue;
- unsigned int *flags;
- unsigned int *next_seq;
- {
- char *sd;
-
- if( (sd = get_spool_dir( queue )) == NULL )
- return -1;
-
- read_lock_file( sd, flags, next_seq );
- free( sd );
-
- return 0;
- }
-
- /*
- * Read the status of the specified queue from memory or disk as necessary
- */
- int
- read_status( queue, flags, next_seq, message )
- char *queue;
- unsigned int *flags;
- unsigned int *next_seq;
- char **message;
- {
- char *primary_name;
- struct LPDstatus *status;
-
- #ifdef LPD_DEBUG
- tprintf( "read_status( %s )\n", queue );
- tflush();
- #endif
-
- if( is_lpd_active() ) { /* Server is active */
-
- primary_name = get_primary_queue_name( queue );
- if( (status = get_status_entry( primary_name )) == NULL ) {
- free( primary_name );
- return -1;
- }
- free( primary_name );
-
- *flags = status->flags;
- *next_seq = status->next_seq;
- *message = status->message;
- } else {
- *message = "LPD server is not active";
- return( load_status( queue, flags, next_seq ) );
- }
-
- return 0;
- }
-
- /*
- * Set the flag bits specified in the queue status entry
- */
- int
- set_status_flag( queue, flag )
- char *queue;
- int flag;
- {
- unsigned int flags, next_seq;
- char *message;
-
- if( read_status( queue, &flags, &next_seq, &message ) < 0 )
- return -1;
-
- flags |= flag;
-
- if( save_status( queue, flags, next_seq ) < 0 )
- return -1;
-
- return 0;
- }
-
- /*
- * Clear the flag bits specified in the queue status entry
- */
- int
- clear_status_flag( queue, flag )
- char *queue;
- int flag;
- {
- unsigned int flags, next_seq;
- char *message;
-
- if( read_status( queue, &flags, &next_seq, &message ) < 0 )
- return -1;
-
- flags &= ~flag;
-
- if( save_status( queue, flags, next_seq ) < 0 )
- return -1;
-
- return 0;
- }
-
- int
- save_status( queue, flags, next_seq )
- char *queue;
- unsigned int flags;
- unsigned int next_seq;
- {
- char *sd, *primary_name;
- struct LPDstatus *status;
-
- #ifdef LPD_DEBUG
- tprintf( "save_status( %s )\n", queue );
- tflush();
- #endif
-
- if( is_lpd_active() ) { /* Server is active */
-
- primary_name = get_primary_queue_name( queue );
- if( (status = get_status_entry( primary_name )) == NULL ) {
- free( primary_name );
- return -1;
- }
- free( primary_name );
- status->flags = flags;
- status->next_seq = next_seq;
- }
-
- if( (sd = get_spool_dir( queue )) == NULL )
- return -1;
-
- write_lock_file( sd, flags, next_seq );
- free( sd );
-
- return 0;
- }
-
- /*
- * Signal a paused printer
- */
- int
- signal_queue( queue )
- char *queue;
- {
- unsigned int flags, next_seq;
- char *message, *primary_name;
- struct LPDstatus *status;
-
- if( read_status( queue, &flags, &next_seq, &message ) < 0 )
- return -1;
-
- flags &= ~PAUSED;
-
- if( save_status( queue, flags, next_seq ) < 0 )
- return -1;
-
- primary_name = get_primary_queue_name( queue );
- if( (status = get_status_entry( primary_name )) == NULL ) {
- free( primary_name );
- return -1;
- }
- free( primary_name );
-
- psignal( &status->flags, 1 );
-
- return 0;
- }
-
- /*
- * Kill the unspooler currently handling the given queue
- */
- int
- kill_unspooler( queue )
- char *queue;
- {
- char *primary_name;
- struct LPDstatus *status;
-
- primary_name = get_primary_queue_name( queue );
- if( (status = get_status_entry( primary_name )) == NULL ) {
- free( primary_name );
- return -1;
- }
- free( primary_name );
-
- if( status->unspooler_proc != NULLPROC ) {
- killproc( status->unspooler_proc );
- status->unspooler_proc = NULLPROC;
- return 1;
- }
- return 0;
- }
-
- /*
- * Return the status of an unspooler for the specified queue.
- * Also return the cf_name of the currently active job.
- */
- int
- is_unspooler_active( queue, job )
- char *queue, **job;
- {
- char *primary_name;
- struct LPDstatus *status;
-
- *job = NULL;
- if( is_lpd_active() ) {
- primary_name = get_primary_queue_name( queue );
- if( (status = get_status_entry( primary_name )) == NULL ) {
- free( primary_name );
- return 0; /* nope */
- }
- free( primary_name );
-
- if( status->unspooler_proc == NULLPROC )
- return 0; /* also not */
-
- *job = status->current_job;
- return 1; /* otherwise, must be active */
- }
- return 0; /* server cannot be active */
- }
-
- /*
- * Get the job count for the given queue
- */
- int
- get_job_count( queue )
- char *queue;
- {
- char *path, *sd;
- unsigned int job_count = 0;
- struct ffblk file_info;
-
- if( (sd = get_spool_dir( queue )) == NULL )
- return -1;
-
- path = pathname( sd, "cf*.*" );
- free( sd );
- if( findfirst( path, &file_info, 0 ) == 0 ) {
- job_count++;
- while( findnext( &file_info ) == 0 )
- job_count++;
- }
- free( path );
-
- YIELD;
- return( job_count );
- }
-
- /*
- * Return the primary queue name of the (possibly) given queue alias
- */
- static char *
- get_primary_queue_name( queue )
- char *queue;
- {
- char *bp, *primary_name;
-
- bp = (char *)mallocw( 1024 );
-
- /* look up corresponding printcap entry */
-
- if( (primary_name = pc_get_entry( bp, queue )) == NULL ) {
- free( bp );
- return NULL;
- }
- free( bp );
-
- return( primary_name );
- }
-
- /*
- * locate device entry for the specified printer device
- */
- struct LPDdevice *
- get_device_entry( device_name )
- char *device_name;
- {
- struct LPDdevice *dptr;
-
- dptr = device_list;
- while( dptr->name != NULL ) {
- if( strcmp( dptr->name, device_name ) == 0 )
- return( dptr );
- dptr++;
- }
- return( NULL ); /* not found */
- }
-
- /*
- * locate status entry for the specified queue
- */
- struct LPDstatus *
- get_status_entry( queue )
- char *queue;
- {
- struct LPDstatus *sptr;
-
- sptr = queue_list;
- while( sptr->name != NULL ) {
- if( strcmp( sptr->name, queue ) == 0 )
- return( sptr );
- sptr++;
- }
- return( NULL ); /* not found */
- }
-
- /*
- * Internal status message routine
- */
- static void
- i_set_status_message( char **dest, char *message, va_list args )
- {
- char buffer[128];
-
- vsprintf( buffer, message, args );
- rip( buffer );
- if( *dest != NULL )
- free( *dest );
- *dest = strdup( buffer );
- }
-
- /*
- * Set the status message as specified
- */
- void
- set_status_message( char **dest, char *message, ... )
- {
- va_list args;
-
- va_start( args, message );
- i_set_status_message( dest, message, args );
- va_end( args );
- }
-
- /*
- * Return a pointer to a static data area containing the formatted date
- * and time.
- */
- char *
- time_string(void)
- {
- time_t current_time;
-
- time( ¤t_time );
- return( ctime( ¤t_time ) );
- }
-
- /*
- * Internal log routine
- */
- static void
- i_lpd_log( struct LPDtrans *LPD, char *message, va_list args )
- {
- char buffer[128], timeb[30];
-
- vsprintf( buffer, message, args );
- strcpy( timeb, time_string() );
- rip( timeb );
- fputs( timeb, LPD->logfp );
- fputs( " - ", LPD->logfp );
- fputs( buffer, LPD->logfp );
- putc( '\n', LPD->logfp );
- }
-
- /*
- * Log a message to the logfile
- */
- void
- lpd_log( struct LPDtrans *LPD, char *message, ... )
- {
- va_list args;
-
- if( LPD->logfp == NULL ) /* no logging */
- return;
-
- va_start( args, message );
- i_lpd_log( LPD, message, args );
- va_end( args );
- }
-